package com.wlf.admin.common.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.router.SaRouterStaff;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wlf.admin.system.domain.SysMenu;
import org.slf4j.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * springMVC配置类
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    private static final Logger log = org.slf4j.LoggerFactory.getLogger(WebMvcConfig.class);

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 拦截器，定义详细认证规则
        registry.addInterceptor(getSaInterceptor()).addPathPatterns("/**");
    }

    // sa-token过滤器
    private SaInterceptor getSaInterceptor() {
        // 不需要登录便可以访问的接口
        final List<String> loginNotUrl
                = ListUtil.of("/login", "/logout", "/static/**", "/error/**", "/captcha", "/captchaCheck");

        return new SaInterceptor(handler -> {
            String requestPath = SaHolder.getRequest().getRequestPath();
            SaRouterStaff baseRouter = SaRouter.match("/**")    // 拦截的 path 列表，可以写多个 */
                    // 登陆鉴权校验忽略url
                    .notMatch(loginNotUrl);
            // 登陆校验
            baseRouter
                    .check(r -> log.debug("登录校验requestPath=" + requestPath))
                    .check(r -> StpUtil.checkLogin())
                    // 权限校验
                    .notMatch("/") // 权限校验忽略URL
                    .check(r -> {
                        log.debug("权限校验requestPath=" + requestPath);
                        // 如果 登陆用户ID为 1 , 则跳过权限校验
                        if ("1".equals(StpUtil.getLoginIdAsString())) {
                            log.debug("1用户为开发用户,不进行权限校验");
                            SaRouter.stop();
                        }
                        String path = StrUtil.subSuf(requestPath, 1);
                        SysMenu sysMenu = Db.lambdaQuery(SysMenu.class).eq(SysMenu::getUrl, path).one();
                        if (sysMenu == null) {
                            // 如果菜单表中未定义此url的信息，则直接返回无权限
                            throw new NotPermissionException("未定义url:" + path + "对应菜单数据,请维护", StpUtil.getLoginType()).setCode(SaErrorCode.CODE_11051);
                        }
                        // 定义过后则判断当前登陆用户是否存在此权限
                        StpUtil.checkPermission(sysMenu.getAuth());
                    });
        });
    }
}

